from redis import asyncio as aioredis
from app.config.config import settings
import json
import logging

logger = logging.getLogger(__name__)

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, '__dict__'):
            return obj.__dict__
        try:
            return str(obj)
        except:
            return None

class RedisClient:
    _instance = None
    
    def __init__(self):
        self.redis = None
        
    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance
    
    async def init_connection(self):
        """初始化 Redis 连接"""
        try:
            self.redis = aioredis.Redis(
                host=settings.REDIS_HOST,
                port=settings.REDIS_PORT,
                db=settings.REDIS_DB,
                password=settings.REDIS_PASSWORD,
                decode_responses=True,
                socket_timeout=5,
                socket_connect_timeout=5
            )
            # 测试连接
            await self.redis.ping()
            logger.info("Redis connection established successfully")
        except Exception as e:
            logger.error(f"Failed to initialize Redis connection: {str(e)}")
            self.redis = None
            raise
        
    async def get_connection(self) -> aioredis.Redis:
        """获取 Redis 连接，如果没有则初始化"""
        if self.redis is None:
            await self.init_connection()
        else:
            try:
                await self.redis.ping()
            except (aioredis.ConnectionError, aioredis.TimeoutError):
                await self.init_connection()
        return self.redis

    async def set_data(self, key: str, data: dict, expire: int = 1800):
        """存储数据到Redis"""
        if self.redis is None:
            await self.init_connection()
        try:
            serialized_data = json.dumps(data, cls=CustomJSONEncoder)
            await self.redis.setex(key, expire, serialized_data)
        except Exception as e:
            logger.error(f"Failed to set data in Redis: {str(e)}")
            raise

    async def get_data(self, key: str) -> dict:
        """从Redis获取数据"""
        if self.redis is None:
            await self.init_connection()
        try:
            data = await self.redis.get(key)
            if data:
                return json.loads(data)
            return None
        except Exception as e:
            logger.error(f"Failed to get data from Redis: {str(e)}")
            raise

    async def delete_data(self, key: str):
        """删除Redis中的数据"""
        if self.redis is None:
            await self.init_connection()
        try:
            await self.redis.delete(key)
        except Exception as e:
            logger.error(f"Failed to delete data from Redis: {str(e)}")
            raise

    async def update_data(self, key, value):
        """
        更新Redis中的数据。
        
        :param key: 要更新的键
        :param value: 新的值
        :return: 更新操作的结果
        """
        if self.redis is None:
            await self.init_connection()
        try:
            serialized_value = json.dumps(value)
            await self.redis.set(key, serialized_value)
            return True
        except Exception as e:
            print(f"Error updating data in Redis: {e}")
            return False

# 创建全局Redis客户端实例
redis_client = RedisClient.get_instance() 